namespace SimpleWebServices.Security.Cryptography
{
    using System;
    using SimpleWebServices;
    using Xunit;

    public sealed class SecureHashFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<SecureHash>()
                .DerivesFrom<object>()
                .IsConcreteClass()
                .IsSealed()
                .NoDefaultConstructor()
                .Result);
        }

        [Fact]
        public void ctor_stringNull()
        {
            Assert.Throws<ArgumentNullException>(() => new SecureHash(null));
        }

        [Fact]
        public void ctor_stringEmpty()
        {
            Assert.Throws<ArgumentOutOfRangeException>(() => new SecureHash(string.Empty));
        }

        [Fact]
        public void ctor_string()
        {
            Assert.NotNull(new SecureHash("XbAH5ybjSkZt+Q=="));
        }

        [Fact]
        public void opEquality_SecureHash_SecureHashTrue()
        {
            string value = "XbAH5ybjSkZt+Q==";

            SecureHash obj = new SecureHash(value);
            SecureHash comparand = new SecureHash(value);

            Assert.True(obj == comparand);
        }

        [Fact]
        public void opEquality_SecureHash_SecureHashFalse()
        {
            SecureHash obj = new SecureHash("XbAH5ybjSkZt+Q==");
            SecureHash comparand = SecureHash.Encrypt("plaintext", new Salt());

            Assert.False(obj == comparand);
        }

        [Fact]
        public void opEquality_SecureHash_SecureHashNull()
        {
            Assert.False(SecureHash.Encrypt("plaintext", new Salt()) == null);
        }

        [Fact]
        public void opEquality_SecureHashNull_SecureHash()
        {
            Assert.False(null == SecureHash.Encrypt("plaintext", new Salt()));
        }

        [Fact]
        public void opEquality_SecureHash_SecureHashSame()
        {
            SecureHash obj = new SecureHash("XbAH5ybjSkZt+Q==");
            SecureHash comparand = obj;

            Assert.True(obj == comparand);
        }

        [Fact]
        public void opImplicit_string_SecureHashNull()
        {
            string expected = null;
            string actual = null as SecureHash;

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void opImplicit_string_SecureHash()
        {
            string expected = "XbAH5ybjSkZt+Q==";
            string actual = new SecureHash(expected);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void opImplicit_SecureHash_stringNull()
        {
            SecureHash expected = null;
            SecureHash actual = null as string;

            Assert.Equal<SecureHash>(expected, actual);
        }

        [Fact]
        public void opImplicit_SecureHash_stringEmpty()
        {
            try
            {
            SecureHash obj = string.Empty;
            }
            catch (ArgumentOutOfRangeException)
            {
            }
        }

        [Fact]
        public void opImplicit_SecureHash_string()
        {
            string value = "XbAH5ybjSkZt+Q==";

            SecureHash expected = new SecureHash(value);
            SecureHash actual = value;

            Assert.Equal<SecureHash>(expected, actual);
        }

        [Fact]
        public void opInequality_SecureHash_SecureHashTrue()
        {
            SecureHash obj = new SecureHash("XbAH5ybjSkZt+Q==");
            SecureHash comparand = SecureHash.Encrypt("plaintext", new Salt());

            Assert.True(obj != comparand);
        }

        [Fact]
        public void opInequality_SecureHash_SecureHashFalse()
        {
            string value = "XbAH5ybjSkZt+Q==";

            SecureHash obj = new SecureHash(value);
            SecureHash comparand = new SecureHash(value);

            Assert.False(obj != comparand);
        }

        [Fact]
        public void opInequality_SecureHash_SecureHashNull()
        {
            Assert.True(SecureHash.Encrypt("plaintext", new Salt()) != null);
        }

        [Fact]
        public void opInequality_SecureHashNull_SecureHash()
        {
            Assert.True(null != SecureHash.Encrypt("plaintext", new Salt()));
        }

        [Fact]
        public void opInequality_SecureHash_SecureHashSame()
        {
            SecureHash obj = new SecureHash("XbAH5ybjSkZt+Q==");
            SecureHash comparand = obj;

            Assert.False(obj != comparand);
        }

        [Fact]
        public void op_Encrypt_string_Salt()
        {
            Salt salt = "XbAH5ybjSkZt+Q==";

            SecureHash expected = new SecureHash("4bF4xJX9VVDr+xFMuOWS/9wJLAc7/ByDjW2PgPp5YLc=");
            SecureHash actual = SecureHash.Encrypt("plaintext", salt);

            Assert.Equal<SecureHash>(expected, actual);
        }

        [Fact]
        public void op_Encrypt_stringEmpty_Salt()
        {
            Salt salt = "XbAH5ybjSkZt+Q==";

            SecureHash expected = new SecureHash("2uI+DajQR+GeYNTccNcDjoE5UtXbF6Jr+kVtE4vcNn4=");
            SecureHash actual = SecureHash.Encrypt(string.Empty, salt);

            Assert.Equal<SecureHash>(expected, actual);
        }

        [Fact]
        public void op_Encrypt_stringNull_Salt()
        {
            Assert.Throws<ArgumentNullException>(() => SecureHash.Encrypt(null, new Salt()));
        }

        [Fact]
        public void op_Encrypt_string_SaltNull()
        {
            Assert.Throws<ArgumentNullException>(() => SecureHash.Encrypt("plaintext", null));
        }

        [Fact]
        public void op_Equals_objectSame()
        {
            SecureHash obj = SecureHash.Encrypt("plaintext", new Salt());

            Assert.True(obj.Equals(obj as object));
        }

        [Fact]
        public void op_Equals_objectNull()
        {
            Assert.False(SecureHash.Encrypt("plaintext", new Salt()).Equals(null as object));
        }

        [Fact]
        public void op_Equals_objectString()
        {
            string value = "XbAH5ybjSkZt+Q==";
            SecureHash obj = new SecureHash(value);

            Assert.False(obj.Equals(value as object));
        }

        [Fact]
        public void op_Equals_objectTrue()
        {
            string value = "XbAH5ybjSkZt+Q==";
            SecureHash obj = new SecureHash(value);
            SecureHash comparand = new SecureHash(value);

            Assert.True(obj.Equals(comparand as object));
        }

        [Fact]
        public void op_Equals_objectFalse()
        {
            SecureHash obj = SecureHash.Encrypt("plaintext", new Salt());
            SecureHash comparand = new SecureHash("XbAH5ybjSkZt+Q==");

            Assert.False(obj.Equals(comparand as object));
        }

        [Fact]
        public void op_GetHashCode()
        {
            string value = "XbAH5ybjSkZt+Q==";

            int expected = value.GetHashCode();
            int actual = new SecureHash(value).GetHashCode();

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_ToString()
        {
            string expected = "XbAH5ybjSkZt+Q==";
            string actual = new SecureHash(expected).ToString();

            Assert.Equal<string>(expected, actual);
        }
    }
}